package com.imooc.security.browser;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;

import com.imooc.security.core.properties.SecurityProperties;
import com.imooc.security.core.validate.code.ValidateCodeFilter;
/**
 * 认证校验配置信息
 * @author Jon
 *
 */
@Configuration
public class BrowserSecurityConfig extends WebSecurityConfigurerAdapter{
	
	@Autowired
	private SecurityProperties securityProperties;
	
	@Autowired
	private AuthenticationSuccessHandler authenticationSuccessHandler;
	
	@Autowired
	private AuthenticationFailureHandler authenticationFailureHandler;
	
	@Autowired
	private DataSource dataSource;
	
	@Autowired
	private UserDetailsService userDetailsService;
	
	/**   
	 * Description  注入加密对象		
	 * @return  
	 */ 
	@Bean
	public PasswordEncoder passwordEncoder() {
		return new BCryptPasswordEncoder();
	}
	
	/**
	 * 读写数据库配置
	 */
	@Bean
	public PersistentTokenRepository persistentTokenRepository() {
		JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();
		tokenRepository.setDataSource(dataSource);//设置数据源
		//tokenRepository.setCreateTableOnStartup(true);//启动自动创建表
		return tokenRepository;
	}

	@Override
	protected void configure(HttpSecurity http) throws Exception {
		
		//配置过滤器信息
		ValidateCodeFilter validateCodeFilter = new ValidateCodeFilter();
		validateCodeFilter.setAuthenticationFailureHandler(authenticationFailureHandler);
		validateCodeFilter.setSecurityProperties(securityProperties);
		validateCodeFilter.afterPropertiesSet();
		
		http.addFilterBefore(validateCodeFilter, UsernamePasswordAuthenticationFilter.class)//在UsernamePasswordAuthenticationFilter前添加自己的过滤器
			.formLogin()//表单认证
				.loginPage("/authentication/require")//登录页面
				.loginProcessingUrl("/authentication/form")//指定该请求匹配SpringSecurity默认的/login请求
				.successHandler(authenticationSuccessHandler)//登录成功后处理
				.failureHandler(authenticationFailureHandler)
				.and()
			.rememberMe()//"记住我"配置
				.tokenRepository(persistentTokenRepository())//配置数据
				.tokenValiditySeconds(securityProperties.getBrowser().getRemeberMeSeconds())//配置时间
				.userDetailsService(userDetailsService)//配置验证逻辑（已经被实现过了）
				.and()
			.authorizeRequests()//下面都是授权配置
				.antMatchers("/authentication/require",
						securityProperties.getBrowser().getLoginPage()
						,"/code/image").permitAll()//跳入此页面不需要验证（防止循环验证）
				.anyRequest()//任何请求
				.authenticated()//都需要身份认证
				.and()
			.csrf().disable();//关闭跨站伪造防护功能
	}
}
